﻿using FPSO.Models.Domain;
using Microsoft.Practices.Prism;
using System;
using System.Collections.Generic;
using System.Data.Odbc;
using System.Net;
using System.Windows.Media;
using System.Xml;
using static FPSO.Models.Constant.TankConstant;

namespace FPSO.Models.Constant
{
    public class TankConstant
    {
		//DEBUG 实船测试版本控制，用于快速切换对部分数据库软件的依赖关系
		//[实船调试] 通过g_Onboard实现辅助决策和在线监控版本的控制

		public static bool g_Onboard = true;
		public static bool g_OnboardPreCheck = false;
		public static bool g_Debug = false;

		//DEBUG 此处增加若干list，用于保存本程序从opc获得的原始数据
		//该数据直接用于OPCMonitorView及其他监测页面中数据的显示

		public static List<OPCTag> tagList_tankStatus;
		public static List<OPCTag> tagList_valveStatus;
		public static List<OPCTag> tagList_pumpStatus;
		public static List<OPCTag> tagList_flammableGasStatus;
		public static List<OPCTag> tagList_hardwireStatus;

		public static List<ConstantTankInfo> ConstantList = new List<ConstantTankInfo>();
        public static Dictionary<string, ConstantTagInfo> ConstantTagDic = new Dictionary<string, ConstantTagInfo>();
        private static Dictionary<string, ConstantTankInfo> IdToInfoDic = new Dictionary<string, ConstantTankInfo>();

        //静态设备字典
        private static Dictionary<string, ConstantDeviceInfo> ConstantDeviceDic  = new Dictionary<string, ConstantDeviceInfo>();

		//不同任务对应关系
		public static Dictionary<string, ConstantTaskInfo> ConstantCargoLoadTaskDeviceDic = new Dictionary<string, ConstantTaskInfo>();
		public static Dictionary<string, ConstantTaskInfo> ConstantCargoUnloadTaskDeviceDic = new Dictionary<string, ConstantTaskInfo>();
		public static Dictionary<string, ConstantTaskInfo> ConstantCargoSwapTaskDeviceDic = new Dictionary<string, ConstantTaskInfo>();
		public static Dictionary<string, ConstantTaskInfo> ConstantBallastLoadTaskDeviceDic = new Dictionary<string, ConstantTaskInfo>();
		public static Dictionary<string, ConstantTaskInfo> ConstantBallastUnloadTaskDeviceDic = new Dictionary<string, ConstantTaskInfo>();

		//[实船调试] 暂时按这种方式记录当前舱室液位高取值的传感器，后面需做成交互界面，开放给用户制定
		public static List<Int16> g_TargetBwtLevelIdx = new List<Int16> { 22, 23, 25, 28, 29, 32, 33, 35, 37, 39 };
		public static List<Int16> g_TargetCotLevelIdx = new List<Int16> { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };

		public static string logSaveFilePath = "..\\..\\log";
		public static logs MyLog;
		public static string datalogSaveFilePath = "..\\..\\Datalog";
		public static logs MyDataLog;

		static TankConstant()
        {			
			ConstantList = new List<ConstantTankInfo>();
            XmlDocument doc = new XmlDocument();
			doc.Load("./TankRes.xml");

            //加载舱室
            XmlNode tanksNode = doc.SelectSingleNode("/resconfig/tanks");
            XmlNodeList tankNodes = tanksNode.SelectNodes("tank");

            Console.Out.Write("加载舱室");
			foreach (XmlNode tankNode in tankNodes)
			{
				ConstantList.Add(new ConstantTankInfo(tankNode.Attributes["id"].Value, tankNode.Attributes["id"].Value, tankNode.Attributes["name"].Value, double.Parse(tankNode.Attributes["volume"].Value)));
            }

            IdToInfoDic = new Dictionary<string, ConstantTankInfo>();
            foreach (ConstantTankInfo tank in ConstantList)
            {
                try
                {
                    IdToInfoDic.Add(tank.TankID, tank);
                }
                catch
                {
                    double a = 0;
                }
            }


            //加载设备
            XmlNode devicesNode = doc.SelectSingleNode("/resconfig/devices");
            XmlNodeList deviceNodes = devicesNode.SelectNodes("device");

            Console.Write("加载设备");
            foreach (XmlNode deviceNode in deviceNodes)
            {
                ConstantDeviceInfo deviceInfo = new ConstantDeviceInfo(deviceNode.Attributes["id"].Value, deviceNode.Attributes["name"].Value, deviceNode.Attributes["type"].Value);

                XmlNodeList tagNodes = deviceNode.SelectNodes("Tag");
                foreach(XmlNode tagNode in tagNodes)
                {
                    ConstantTagInfo tagInfo = new ConstantTagInfo(tagNode.Attributes["TagID"].Value, tagNode.Attributes["OPCTag"].Value, tagNode.Attributes["OpcType"].Value, Convert.ToDouble(tagNode.Attributes["Coeff"].Value));
                    deviceInfo.TagInfos.Add(tagInfo);
                    ConstantTagDic.Add(tagInfo.TagID, tagInfo);
                }

                ConstantDeviceDic.Add(deviceNode.Attributes["id"].Value, deviceInfo);
            }

            //加载任务及对应关系
            XmlNode tasksNode = doc.SelectSingleNode("/resconfig/tasks");
            XmlNodeList taskNodes = tasksNode.SelectNodes("task");

            Console.Write("加载任务及对应关系");

            foreach (XmlNode taskNode in taskNodes)
            {
                int taskType = int.Parse(taskNode.Attributes["id"].Value);

                XmlNodeList taskInfoNodes = taskNode.SelectNodes("taskinfo");

                foreach(XmlNode taskInfoNode in taskInfoNodes)
                {
                    ConstantTaskInfo taskInfo = new ConstantTaskInfo();
                    taskInfo.SourceTank = taskInfoNode.Attributes["sourcetank"].Value;
                    taskInfo.TargetTank = taskInfoNode.Attributes["targettank"].Value;

                    XmlNodeList taskDevNodes = taskInfoNode.SelectNodes("device");

                    foreach(XmlElement devNode in taskDevNodes)
                    {
                        ConstantTaskDevice constantTaskDevice = new ConstantTaskDevice(devNode.Attributes["id"].Value, int.Parse(devNode.Attributes["optindex"].Value), devNode.Attributes["tagId"].Value.Split(','), devNode.Attributes["operate"].Value.Split(','));
                        taskInfo.TaskDevices.Add(constantTaskDevice);
                    }

                    if (taskType == TaskTypeConstant.LOAD_ID)
                    {
						ConstantCargoLoadTaskDeviceDic.Add(taskInfo.SourceTank + "-" + taskInfo.TargetTank, taskInfo);
                    }
                    if (taskType == TaskTypeConstant.UNLOAD_ID)
                    {
						ConstantCargoUnloadTaskDeviceDic.Add(taskInfo.SourceTank + "-" + taskInfo.TargetTank, taskInfo);
                    }
                    if (taskType == TaskTypeConstant.SWAP_ID)
                    {
						ConstantCargoSwapTaskDeviceDic.Add(taskInfo.SourceTank + "-" + taskInfo.TargetTank, taskInfo);
                    }
                    if (taskType == TaskTypeConstant.BALLAST_ID)
                    {
						ConstantBallastLoadTaskDeviceDic.Add(taskInfo.SourceTank + "-" + taskInfo.TargetTank, taskInfo);
                    }
                    if (taskType == TaskTypeConstant.UNBALLAST_ID)
                    {
						ConstantBallastUnloadTaskDeviceDic.Add(taskInfo.SourceTank + "-" + taskInfo.TargetTank, taskInfo);

                    }
                }
            }
		}

        public static string GetTankName(string tankId)
        {
            return IdToInfoDic[tankId].TankName;
        }

        public static string GetTankId(string tankName)
        {
            foreach(var tankInfo in ConstantList)
            {
                if(tankInfo.TankName == tankName)
                {
                    return tankInfo.TankID;
                }
            }
            return "";
        }

        public static double GetTankVolume(string tankId)
        {
            return IdToInfoDic[tankId].TankVolume;
        }

		public static double GetCurrentTankInn(string tankId)
		{
			foreach(OPCTag tanktag in tagList_tankStatus)
			{
				if(tanktag.DispName.Contains(tankId) && tanktag.DispName.Contains("LEVEL") && !tanktag.DispName.Contains("LEVEL1"))
				{
					return Convert.ToDouble(tanktag.OpcValue.Value) * TankConstant.TANKLEVEL_PARAM;
				}
			}
			return 0.0;
		}
        public static double GetTankTotleVolume()
        {
            double val = 0d;
            foreach(ConstantTankInfo tankInfo in ConstantList)
            {
                val = val + tankInfo.TankVolume;
            }

            return val;
        }

		public static int GetTanksCount()
		{
			return ConstantList.Count;

        }

        public static ConstantDeviceInfo getDeviceInfo(string deviceId)
        {
            return ConstantDeviceDic[deviceId];
        }
		public static List<ConstantTaskDevice> GetTaskRelationValve(string fromtank,string totank,int taskType)
        {
            if (taskType == TaskTypeConstant.LOAD_ID)
            {
                if(ConstantCargoLoadTaskDeviceDic.ContainsKey(fromtank+"-"+totank))
                {
                    return ConstantCargoLoadTaskDeviceDic[fromtank + "-" + totank].TaskDevices;
                }
            }
            if (taskType == TaskTypeConstant.UNLOAD_ID)
            {
                if (ConstantCargoUnloadTaskDeviceDic.ContainsKey(fromtank + "-" + totank))
                {
                    return ConstantCargoUnloadTaskDeviceDic[fromtank + "-" + totank].TaskDevices;
                }
            }
            if (taskType == TaskTypeConstant.SWAP_ID)
            {
                if (ConstantCargoSwapTaskDeviceDic.ContainsKey(fromtank + "-" + totank))
                {
                    return ConstantCargoSwapTaskDeviceDic[fromtank + "-" + totank].TaskDevices;
                }
            }
            if (taskType == TaskTypeConstant.BALLAST_ID)
            {
                if (ConstantBallastLoadTaskDeviceDic.ContainsKey(fromtank + "-" + totank))
                {
                    return ConstantBallastLoadTaskDeviceDic[fromtank + "-" + totank].TaskDevices;
                }
            }
            if (taskType == TaskTypeConstant.UNBALLAST_ID)
            {
                if (ConstantBallastUnloadTaskDeviceDic.ContainsKey(fromtank + "-" + totank))
                {
                    return ConstantBallastUnloadTaskDeviceDic[fromtank + "-" + totank].TaskDevices;
                }

            }

            return null;
        }

        /// <summary>
        /// 判断舱室是否是货舱
        /// </summary>
        /// <param name="tankId"></param>
        /// <returns></returns>
        public static bool TankIdIsCOT(string tankId)
        {
			return tankId.IndexOf("COT") > 0;
        }

		//NOTICE 这里不考虑APT，APT走的是单独的压载路线
        public static List<ConstantTankInfo> getWBTTank()
        {
            List<ConstantTankInfo> names = new List<ConstantTankInfo>();
            foreach( var tankInfo in ConstantList)
            {
				if(tankInfo.TankID.IndexOf("WBT") >0 || tankInfo.TankID.IndexOf("FPT") >= 0)
                {
					names.Add(tankInfo);
                }
            }
            return names;
        }

		public static List<ConstantTankInfo> getCOTTank()
		{
			List<ConstantTankInfo> names = new List<ConstantTankInfo>();
			foreach (var tankInfo in ConstantList)
			{
				if (tankInfo.TankID.IndexOf("COT") > 0)
				{
					names.Add(tankInfo);
				}
			}
			return names;
		}
		public class ConstantTankInfo
        {
            public ConstantTankInfo(string tankId, string tankAbname, string tankName, double tankVolume)
            {
                TankID = tankId;
				TankAbName = tankAbname;
				TankName = tankName;
                TankVolume = tankVolume;
            }

            public string TankID { get; set; }
			public string TankAbName { get; set; }
			public string TankName { get; set; }
            public double TankVolume { get; set; }
        }

        public class ConstantTagInfo
        {
            public ConstantTagInfo(string tagID, string oPCTag, string opcType, double coeff)
            {
                TagID = tagID;
                OPCTag = oPCTag;
                OpcType = opcType;
                Coeff = coeff;
            }

            public string TagID { get; set; }
            public string OPCTag { get; set; }
            public string OpcType { get; set; }
            public double Coeff { get; set; }
        }

        public class ConstantDeviceInfo
        {
            private List<ConstantTagInfo> tagInfo = new List<ConstantTagInfo>();
            public ConstantDeviceInfo(string deviceId, string deviceName, string deviceType)
            {
                DeviceId = deviceId;
                DeviceName = deviceName;
                if (deviceType.ToLower() == "valve")
                {
                    DeviceType = DEVICE_TYPE.VALVE;
                }
                else
                {
                    DeviceType = DEVICE_TYPE.PUMP;
                }

            }

            public string getDeviceType()
            {
                if (DeviceType == DEVICE_TYPE.VALVE)
                {
                    return "阀门";
                }
                else
                {
                    return "泵";
                }
            }

            public string DeviceId { get; set; }
            public string DeviceName { get; set; }
            public DEVICE_TYPE DeviceType { get; set; }
            public List<ConstantTagInfo> TagInfos { get { return tagInfo; } }
        }

        public class ConstantTaskInfo
        {
            public ConstantTaskInfo()
            {
                SourceTank = "";
                TargetTank = "";
                TaskDevices = new List<ConstantTaskDevice>();
            }

            public string SourceTank  { get; set; }
            public string TargetTank  { get; set; }
            public List<ConstantTaskDevice> TaskDevices  { get; set; }
        }

        public class ConstantTaskDevice
        {
            private List<string> tagIds = new List<string>();
            private List<DEVICE_OPERATE> operates = new List<DEVICE_OPERATE>(); 

            public ConstantTaskDevice(string deviceId, int optindex, string[] tagId, string[] operate)
            {
                DeviceId = deviceId;
                Optindex = optindex;
                foreach (string tag in tagId)
                {
                    tagIds.Add(tag);
                }
                foreach (string op in operate)
                {
                    operates.Add((DEVICE_OPERATE)int.Parse(op));
                }    
            }

            public string getPlanState(string tagId)
            {
                int index = tagIds.IndexOf(tagId);
                if (index == -1) { return ""; }

                DEVICE_OPERATE op = operates[index];
                string opt = "";
                if(op == DEVICE_OPERATE.TRUE)
                {
                    opt = "O";
                }
                else
                {
                    opt = "C";
                }

                return opt + "/" + Optindex;
            }
             
            public string DeviceId { get; set; }
            public List<string> TagIds { get { return tagIds; } }

            public int Optindex { get; set; }
            public List<DEVICE_OPERATE> Operates { get { return operates; } }
        }

        public enum DEVICE_TYPE
        {
            VALVE = 0,
            PUMP = 1,
        }

        public enum DEVICE_OPERATE
        {
            TRUE = 1,
            FALSE = 0,
        }

		//为整个系统设置数据转换的系数，即从通讯传入数据至界面显示数据的倍率
		public const double TANKLEVEL_PARAM = 0.01;
		public const double TANKTEMP_PARAM = 0.01;
		public const double TANKPRESS_PARAM = 1.0;
		public const double DRAFTSTATUS_PARAM = 0.01;
		public const double CALC_PARAM = 1.0;

		public const int MAXPUMPPRESS = 220;

	}
}
